iT邦幫忙

2023 iThome 鐵人賽

DAY 14
0
Mobile Development

即使明天老闆突然叫你用 React Native 也可以跟他說好沒問題系列 第 14

Day 14. 以 React Navigation 建立路由表、切換頁面

  • 分享至 

  • xImage
  •  

認識 React Navigation 與建立路由表

在網站中我們會設定路由表來切換頁面,同樣的在 App 中也會有頁面切換的需求,而 React Navigation 可以幫我們在 React Native 環境中設定路由。截至 2023 年 7 月為止, React Navigation 需搭配 React Native 0.63.0 以上(含)版本。若專案中有用到 TypeScript ,需要 4.1.0 以上(含)版本。

首先在終端機以 npm install @react-navigation/native @react-navigation/native-stack react-native-screens react-native-safe-area-context 下載。同時還須設定 ios ,一樣在終端機 cd ios 移動到 ios 資料夾後以 pod install 下載。

Tips :若移動到 ios 資料夾後要執行其他事,別忘了用 cd .. 移回上層資料夾後再執行。

直接用官網範例程式碼來了解路由和頁面元件怎樣設定。首先我們在 App.jsx 設定一個名為 HomeScreen 頁面元件。

import React from 'react';
import {View, Text} from 'react-native';

function HomeScreen() {
  return (
    <View>
      <Text>Home Screen</Text>
    </View>
  );
}

在最上方載入 NavigationContainer 與 createNativeStackNavigator 。

NavigationContainer 是一個用來管理導覽表的元件,所有 navigator 都必須被包覆在他裡頭。通常都會在根元件中設定與渲染 NavigationContainer 。

createNativeStackNavigator 則是一個函式,會返回一個物件,包著兩個元件: Screen 和 Navigator 。藉由宣告一個變數 Stack ,可以讓我們取用這兩個元件。 Navigator 必須包在 Screen 外,用以定義路由配置;而 Screen 顧名思義負責載入路由表上的頁面元件,必須包含路由名字 name 和要渲染的元件 component 兩個屬性。

import {NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';

const Stack = createNativeStackNavigator();

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

export default App;

完成後應該就會看到最基本的頁面了:
https://ithelp.ithome.com.tw/upload/images/20230916/20129635dG8JIic4YM.png

Tips :若下載後執行範例程式碼報錯,可關閉模擬器重新開啟試試看。

Tips :調整路由表架構後,有時仍會記錄到舊的導致錯誤,可以 ctrl + c 停止專案,重新 npm start 重啟。

接著可以依樣畫葫蘆製作第二個頁面元件 DetailScreen 。可以發現,當我們把 DetailScreen 的 Stack.Screen 移到 HomeScreen 之上時,畫面就會顯示 DetailScreen ;反之,則顯示 HomeScreen 。

function DetailScreen() {
  return (
    <View>
      <Text>Detail Screen</Text>
    </View>
  );
} 

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Detail" component={DetailScreen} />
        <Stack.Screen name="Home" component={HomeScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

若我們不想靠這樣調整順序,預設第一個渲染的畫面, React Navigation 也提供 initialRouteName 屬性來設定。注意!傳入的值必須是 Screen 中設定的 name 。

<NavigationContainer>
  <Stack.Navigator initialRouteName="Detail">
    <Stack.Screen name="Home" component={HomeScreen} />
    <Stack.Screen name="Detail" component={DetailScreen} />
  </Stack.Navigator>
</NavigationContainer>

在 React Navigation 中切換頁面

建立路由表後,我們要怎樣讓使用者在不同頁面間自由切換呢?首先,如果我們已經明確知道要切換過去的元件名稱, 那可以透過在頁面元件傳入 navigation 這個預設的 props ,來使用 navigation.navigate() 跳過去。注意!裡頭傳入的要是 Screen 設定的 name 。

把 HomeScreen 做以下改寫:

function HomeScreen({navigation}) {
  return (
    <View>
      <Text>Home Screen</Text>
      <TouchableOpacity onPress={() => navigation.navigate('Detail')}>
        <Text>切換到 Detail Screen</Text>
      </TouchableOpacity>
    </View>
  );
}

如果要回到上一頁,除了用手機預設的上一頁功能外,我們也可以透過 navigation.goBack() 來實踐。

function HomeScreen({navigation}) {
  return (
    <View>
      ... 省略
      <TouchableOpacity onPress={() => navigation.goBack()}>
        <Text>回上頁</Text>
      </TouchableOpacity>
    </View>
  );
}

在 React Navigation 中傳參數給內頁

假設今天製作的頁面是一個菜單列表,點擊後進入每道菜的介紹頁面。如同之前提過的元件設計邏輯,我們不可能為每道菜製作一個頁面元件,不只會累死自己,也很難維護管理,更何況要秀的內容都一樣。

這時,就可以在點擊菜單列表上的按鈕時,傳一個參數。當進入同個介紹內頁時,再透過該參數來取 API ,秀出對應內容。在 navigation.navigate() 的第二個參數放入一個裝參數的物件,物件的屬性會是取出時使用的名稱,可自由命名,並可不只一個值。在接收參數的 Functional Component 載入 route ,並用物件解構取得包在 params 裡的參數,做後續不同內容渲染。

function HomeScreen({navigation}) {
  return (
    <View>
      <Text>MENU</Text>
      <TouchableOpacity onPress={() => navigation.navigate('Detail', {id: 0})}>
        <Text>滷肉飯</Text>
      </TouchableOpacity>
      <TouchableOpacity onPress={() => navigation.navigate('Detail', {id: 1})}>
        <Text>炒米粉</Text>
      </TouchableOpacity>
    </View>
  );
}
function DetailScreen({navigation, route}) {
  const {id} = route.params;
  return (
    <View>
      <Text>{id}</Text>
      <Text>{id === 0 ? '滷肉飯' : '炒米粉'}</Text>
      <TouchableOpacity onPress={() => navigation.navigate('Home')}>
        <Text>切換到 Home Screen</Text>
      </TouchableOpacity>
    </View>
  );
}

https://ithelp.ithome.com.tw/upload/images/20230916/20129635qIVVFF7bw3.png
https://ithelp.ithome.com.tw/upload/images/20230916/201296350NyZB2eguu.png

透過 console.log() 觀察 route ,會發現他是一個物件。除了傳遞參數的 params 外,還有每次點擊都隨機生成的唯一值 key ,進入的路徑名稱 name ,以及只有透過 deep link 打開才會有的路徑 path 。
https://ithelp.ithome.com.tw/upload/images/20230916/20129635fE8TAkwsgU.png


參考


上一篇
Day 13. 從實作 Tab 選擇器,認識 useEffect
下一篇
Day 15. 以 React Navigation 做路由設定與建立 Bottom Navigation
系列文
即使明天老闆突然叫你用 React Native 也可以跟他說好沒問題30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言